iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
1
自我挑戰組

從色彩繽紛到只看亂碼日子,學程式從 Ruby 出發!系列 第 20

Day20 | Public Private Protected methods

  • 分享至 

  • xImage
  •  

今天來認識Public.Private.Protected方法的存取控制。

Public

放在Public的方法沒有特別限制,大家都可以直接存取。

class A
  def public_method
    puts "我是 public"
  end
end

a = A.new
a.public_method    # 我是 public

Private

private被限制在類別裡才可以存取,不過在Ruby正確的說法是:不能在外部呼叫,也不能明確的指出「接收者」
所以執行a.private_method想要直接在class裡取得private方法,會出現NoMethodErro的錯誤

class A
  def public_method_a
    puts "我是 public"
  end
  
  def public_method_b
    private_method
  end

  private
  def private_method
    puts "我是 private"
  end 
end

a = A.new
a.public_method_a    # 我是 public
a.public_method_b    # 我是 private
a.private_method     # NoMethodError

當B繼承了A,也繼承private方法,所以B類別一樣可以存取private方法。

class A
  def public_method_a
    private_method
  end

  private
  def private_method
    puts "我是 private 來自 class #{self.class}"
  end
end

class B < A
  def public_method_b
    private_method
  end
end

a = A.new
b = B.new
a.public_method_a    # 我是 private 來自 class A
b.public_method_b    # 我是 private 來自 class B

Protected

Protected的性質在Public與Private之間
跟Private有點像,執行a.protected_method想要直接在class裡取得protected方法一樣會出現NoMethodErro的錯誤

class A
  def public_method_a
    puts "我是 public"
  end
  
  def public_method_b
    protected_method
  end

  protected
  def protected_method
    puts "我是 protected"
  end 
end

a = A.new
a.public_method_a     # 我是 public
a.public_method_b     # 我是 protected
a.protected_method    # NoMethodError

private與protected差異

剛剛有說到protected屆於public與private之間,卻又跟private一樣限制在類別裡才可以存取,差異呢?
來試試看以下例子吧!

class A
  def public_method_a
    self.private_method
  end

  def public_method_b
    self.protected_method
  end

  private
  def private_method
    puts "我是 private 來自 class #{self.class}"
  end

  protected
  def protected_method
    puts "我是 protected 來自 class #{self.class}"
  end
end

a = A.new
a.public_method_a    # NoMethodError
a.public_method_b    # 我是 protected 來自 class A

當呼叫方法的接收者是self的時候,private方法依然無法從內部去呼叫,而protected方法就可以。

.send方法

以上,是不是覺得private真的很private,如果聊是非有這樣private的朋友真得很可靠欸!(誤
但事事總是不如我們所想,有的朋友嘴巴比較大(疑?
在Ruby裡private似乎沒有想像中得那麼private喔,先來看看這一段

class Friend
  def gossip
    secret
  end

  private
  def secret
    puts "我跟你說xxx實在很xxx,真討厭!"
  end
end

big_mouth = Friend.new
big_mouth.send(:secret)     # 我跟你說xxx實在很xxx,真討厭!

什麼?!居然直接存取了!秘密被大嘴巴朋友說出去了!
這個.send到底是何方神聖?其實.send是Ruby內建的方法,也是這樣的設計把權限開放給程式設計師,讓開發者有很多彈性空間可以亂玩?欸~不對!是好好去運用它

補充一下:
以上.send方法為例,程式可以寫成

class Friend

  ...(略)
  
  def secret
    puts "我跟你說xxx實在很xxx,真討厭!"
  end
  
  private :secret
end

private :secret這樣的寫法,跟上面是一樣得意思喔!


參考連結:
Public, Protected and Private Method in Ruby
Ruby: public, protected 與 private
類別(Class)與模組(Module)


Wowwww!菜鳥參加鐵人賽不知不覺過2/3了
都沒想過我可以連續寫20天的文章,有種莫名的港動QAQ
還剩1/3加油加油!


上一篇
Day19 | RegExp正規表式法
下一篇
Day21 | nil? empty? blank? present?
系列文
從色彩繽紛到只看亂碼日子,學程式從 Ruby 出發!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言